﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace CodeBetter.Extensions
{
   public static class Enum<T> where T: struct
   {
      public static IEnumerable<T> GetValues()
      {
         return null;
      }
   }

   public static class TypeOf<T>
   {
      public static IEnumerable<T> GetValues(T startValue, T endValue)
      {
         return null;
      }

      public static IEnumerable<T> GetValues()
      {
         Type t = typeof(T);
         if (t.IsEnum)
         {
            foreach (var val in Enum.GetValues(t))
               yield return (T)val;
         }
         else if (t.IsPrimitive)
         {
            if (t == typeof(Single) || t == typeof(Double))
            {
               // not possible
               throw new Exception("Enumerating over values of type " + t.ToString() + " is not possible.");
            }
            else if (t == typeof(Boolean))
            {
               yield return (T)(object)false;
               yield return (T)(object)true;
            }
            else if (t == typeof(Byte))
            {
               for(byte b = byte.MinValue; b < byte.MaxValue; b++)
                  yield return (T)(object)b;
               yield return (T)(object)byte.MaxValue;
            }
            else if (t == typeof(SByte))
            {
               for (sbyte b = sbyte.MinValue; b < sbyte.MaxValue; b++)
                  yield return (T)(object)b;
               yield return (T)(object)sbyte.MaxValue;
            }
            else if (t == typeof(Int32))
            {
               for (int b = int.MinValue; b < int.MaxValue; b++)
                  yield return (T)(object)b;
               yield return (T)(object)int.MaxValue;
            }
            else if (t == typeof(Char))
            {
               for (char b = char.MinValue; b < char.MaxValue; b++)
                  yield return (T)(object)b;
               yield return (T)(object)char.MaxValue;
            }
            // etc
         }
         yield break;
      }

      // GetRange(start, end)
   }

   public static class EnumExtensions
   {
      public static IEnumerable<T> GetValues<T>(this Type type)
      {
         if (type.IsEnum)
         {
            foreach (var val in Enum.GetValues(typeof(T)))
               yield return (T)val;
            yield break;
         }
         if (type.IsPrimitive)
         {
            // The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.
            // Only Double and Single require different handling
         }
         //if (type.UnderlyingSystemType)
         //{
         //}
         yield break;
      }

      public static bool Test123(this Type obj)
      {
         return false;
      }

      public static bool Test<T>(this T type) where T : struct
      {
         return false;
      }

      public static bool Test2(this Enum test)
      {
         return true;
      }

      public enum TestEnum
      {
         One,
         Two
      }

      public static void Test()
      {
         var x = typeof(int).GetValues<int>();
         1.GetType().GetValues<int>();
         TypeOf<int>.GetValues();
         TestEnum p = TestEnum.One;
         bool Test = true;
         Enum.GetValues(typeof(bool));
         // bool.AllValues();
         IEnumerable<bool> tst = typeof(bool).GetValues<bool>();
         Enum<bool>.GetValues();
         Enum<int>.GetValues();
         Enum.GetValues(typeof(bool));
      }


   }
}
